﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;
using YArchitech.Revit.RevitExtension;

namespace YArchitech.Revit
{
	public class HYCreatePipeHelper
	{
		public static List<string> GetElementType(Autodesk.Revit.DB.Document document, Type type)
		{
			IEnumerable<Element> enumerable = new FilteredElementCollector(document).OfClass(type).ToElements();
			List<string> list = new List<string>();
			foreach (Element element in enumerable)
			{
				if (element != null)
				{
					list.Add(element.Name);
				}
			}
			return list;
		}

		public static PipeType GetPipeTypeAccordName(Autodesk.Revit.DB.Document document, string type)
		{
			IEnumerable<Element> enumerable = new FilteredElementCollector(document).OfClass(typeof(PipeType)).ToElements();
			PipeType result = null;
			foreach (Element element in enumerable)
			{
				PipeType pipeType = element as PipeType;
				if (pipeType.Name == type)
				{
					result = pipeType;
					break;
				}
			}
			return result;
		}

		public static PipingSystemType GetPipingSystemTypeAccordName(Autodesk.Revit.DB.Document document, string type)
		{
			IEnumerable<Element> enumerable = new FilteredElementCollector(document).OfClass(typeof(PipingSystemType)).ToElements();
			PipingSystemType result = null;
			foreach (Element element in enumerable)
			{
				PipingSystemType pipingSystemType = element as PipingSystemType;
				if (pipingSystemType.Name == type)
				{
					result = pipingSystemType;
					break;
				}
			}
			return result;
		}

		public void DrawRiserPipe(double x, double y, double zStart, double zEnd, Autodesk.Revit.DB.Document document, PipeType pipeType, string paraDiameter, PipingSystemType pipingSystemType, string lable)
		{
			Level genLevel = document.ActiveView.GenLevel;
			XYZ start = new XYZ(x, y, zStart);
			XYZ end = new XYZ(x, y, zEnd);
			Pipe pipe = document.CreatHYPipe(pipingSystemType, pipeType, genLevel, start, end, double.Parse(paraDiameter));
			pipe.get_Parameter(BuiltInParameter.DOOR_NUMBER).Set(lable);
			ElementTransformUtils.MoveElement(pipe.Document, pipe.Id, new XYZ(1E-05, 1E-05, 1E-05));
			ElementTransformUtils.MoveElement(pipe.Document, pipe.Id, -1.0 * new XYZ(1E-05, 1E-05, 1E-05));
			document.Regenerate();
		}

		public Pipe DrawRiserPipe(XYZ start, XYZ end, Autodesk.Revit.DB.Document document, PipeType pipeType, string paraDiameter, PipingSystemType pipingSystemType)
		{
			Level level = document.ActiveView.GenLevel;
			if (level == null)
			{
				level = YJKRevitTools.GetLevelClose(start, document);
			}
			Pipe result = document.CreatHYPipe(pipingSystemType, pipeType, level, start, end, double.Parse(paraDiameter));
			document.Regenerate();
			return result;
		}

		public void CorrectRiserPipe(Pipe pipe, double zStart, double zEnd, Autodesk.Revit.DB.Document document, PipeType pipeType, string paraDiameter, PipingSystemType pipingSystemType, string lable)
		{
			XYZ hyendPoint = (pipe.Location as LocationCurve).Curve.GetEndPoint(0);
			LocationCurve locationCurve = pipe.Location as LocationCurve;
			XYZ xyz = new XYZ(hyendPoint.X, hyendPoint.Y, zStart);
			XYZ endPoint = new XYZ(hyendPoint.X, hyendPoint.Y, zEnd);
			Level level = document.ActiveView.GenLevel;
			if (level == null)
			{
				level = YJKRevitTools.GetLevelClose(xyz, document);
			}
			Curve curve = YJKLineEx.YJKGetBound(xyz, endPoint);
			locationCurve.Curve = curve;
			pipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set((double)int.Parse(paraDiameter) / 304.8);
			pipe.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM).Set(level.Id);
			pipe.get_Parameter(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM).Set(pipingSystemType.Id);
			pipe.get_Parameter(BuiltInParameter.DOOR_NUMBER).Set(lable);
			pipe.PipeType = pipeType;
			ElementTransformUtils.MoveElement(pipe.Document, pipe.Id, new XYZ(1E-05, 1E-05, 1E-05));
			ElementTransformUtils.MoveElement(pipe.Document, pipe.Id, -1.0 * new XYZ(1E-05, 1E-05, 1E-05));
		}

		public Pipe DrawParallelPipe(Autodesk.Revit.DB.Document document, double offset, string levelOffset, Pipe pipe, PipeType pipeType, string paraDiameter, PipingSystemType pipingSystemType)
		{
			XYZ hyendPoint = (pipe.Location as LocationCurve).Curve.GetEndPoint(0);
			XYZ hyendPoint2 = (pipe.Location as LocationCurve).Curve.GetEndPoint(1);
			Parameter parameter = pipe.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM);
			Level level = document.GetElementById(parameter.AsElementId()) as Level;
			XYZ newParallelPipeXYZ = this.getNewParallelPipeXYZ(hyendPoint, (pipe.Location as LocationCurve).Curve as Line, offset);
			XYZ newParallelPipeXYZ2 = this.getNewParallelPipeXYZ(hyendPoint2, (pipe.Location as LocationCurve).Curve as Line, offset);
			ICollection<ElementId> source = ElementTransformUtils.CopyElement(document, pipe.Id, new XYZ(1.0, 1.0, 0.0));
			Pipe pipe2 = (Pipe)document.GetElementById(source.ElementAt(0));
			LocationCurve locationCurve = pipe2.Location as LocationCurve;
			XYZ xyz = locationCurve.Curve.GetEndPoint(0);
			XYZ xyz2 = locationCurve.Curve.GetEndPoint(1);
			xyz = new XYZ(newParallelPipeXYZ.X, newParallelPipeXYZ.Y, level.ProjectElevation + double.Parse(levelOffset) / 304.8);
			xyz2 = new XYZ(newParallelPipeXYZ2.X, newParallelPipeXYZ2.Y, level.ProjectElevation + double.Parse(levelOffset) / 304.8);
			Line curve = YJKLineEx.YJKGetBound(xyz, xyz2);
			locationCurve.Curve = curve;
			pipe2.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set((double)int.Parse(paraDiameter) / 304.8);
			pipe2.get_Parameter(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM).Set(pipingSystemType.Id);
			pipe2.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM).Set(parameter.AsElementId());
			pipe2.get_Parameter(BuiltInParameter.RBS_OFFSET_PARAM).Set(double.Parse(levelOffset) / 304.8);
			pipe2.PipeType = pipeType;
			double num = pipe.get_Parameter(BuiltInParameter.RBS_PIPE_SLOPE).AsDouble();
			if (num != 0.0)
			{
				double num2 = curve.GetEndPoint(0).DistanceTo(curve.GetEndPoint(1)) * Math.Sin(num);
				if (hyendPoint.Z >= hyendPoint2.Z)
				{
					Line curve2 = YJKLineEx.YJKGetBound(new XYZ(xyz.X, xyz.Y, xyz.Z + num2), xyz2);
					locationCurve.Curve = curve2;
				}
				else
				{
					XYZ endPoint = new XYZ(xyz2.X, xyz2.Y, xyz2.Z + num2);
					Line curve3 = YJKLineEx.YJKGetBound(xyz, endPoint);
					locationCurve.Curve = curve3;
				}
			}
			document.Regenerate();
			ElementTransformUtils.MoveElement(pipe2.Document, pipe.Id, new XYZ(1.0, 1.0, 1.0));
			ElementTransformUtils.MoveElement(pipe2.Document, pipe.Id, -1.0 * new XYZ(1.0, 1.0, 1.0));
			return pipe2;
		}

		public XYZ getNewParallelPipeXYZ(XYZ oldXYZ, Line pipe, double offset)
		{
			XYZ result = null;
			XYZ hyendPoint = pipe.GetEndPoint(0);
			XYZ hyendPoint2 = pipe.GetEndPoint(1);
			Line line = YJKLineEx.YJKGetBound(hyendPoint, hyendPoint2);
			if (Math.Abs(hyendPoint.Y - hyendPoint2.Y) < 1E-09)
			{
				result = new XYZ(oldXYZ.X, oldXYZ.Y + offset / 304.8, oldXYZ.Z);
			}
			else if (Math.Abs(hyendPoint.X - hyendPoint2.X) < 1E-09)
			{
				result = new XYZ(oldXYZ.X - offset / 304.8, oldXYZ.Y, oldXYZ.Z);
			}
			else
			{
				double num = Math.Abs((hyendPoint2.X - hyendPoint.X) / line.Length) * (offset / 304.8);
				double num2 = Math.Abs((hyendPoint2.Y - hyendPoint.Y) / line.Length) * (offset / 304.8);
				if (this.lookForK(hyendPoint, hyendPoint2) < 1E-06)
				{
					result = new XYZ(oldXYZ.X + num2, oldXYZ.Y + num, oldXYZ.Z);
				}
				else if (this.lookForK(hyendPoint, hyendPoint2) > 1E-06)
				{
					result = new XYZ(oldXYZ.X - num2, oldXYZ.Y + num, oldXYZ.Z);
				}
			}
			return result;
		}

		public static Pipe copyPipe(Autodesk.Revit.DB.Document document)
		{
			IEnumerable<Element> enumerable = new FilteredElementCollector(document).OfClass(typeof(Pipe)).ToElements();
			Pipe result = null;
			foreach (Element element in enumerable)
			{
				if (element != null && element is Pipe)
				{
					result = (Pipe)element;
					break;
				}
			}
			return result;
		}

		public static double zCoord(string levelName, double offset, Autodesk.Revit.DB.Document document)
		{
			IList<Element> list = new FilteredElementCollector(document).OfClass(typeof(Level)).ToElements();
			int count = list.Count;
			double result = 0.0;
			foreach (Element element in list)
			{
				if (element != null && element is Level)
				{
					Level level = element as Level;
					if (level.Name == levelName)
					{
						result = level.ProjectElevation + offset / 0.3048;
					}
				}
			}
			return result;
		}

		public Pipe DrawThwartwisePipe(Autodesk.Revit.DB.Document document, double offset, double levelOffset, XYZ start, XYZ end, PipeType pipeType, double paraDiameter, PipingSystemType pipingSystemType, double slope, XYZ pointUser)
		{
			Line pipeline = YJKLineEx.YJKGetBound(start, end);
			XYZ oldXYZ = new XYZ(start.X, start.Y, 0.0);
			XYZ oldXYZ2 = new XYZ(end.X, end.Y, 0.0);
			Level genLevel = document.ActiveView.GenLevel;
			XYZ newParallelPipeXYZ = this.getNewParallelPipeXYZ(oldXYZ, pipeline, offset, pointUser);
			XYZ newParallelPipeXYZ2 = this.getNewParallelPipeXYZ(oldXYZ2, pipeline, offset, pointUser);
			XYZ xyz = new XYZ(newParallelPipeXYZ.X, newParallelPipeXYZ.Y, levelOffset / 304.8);
			XYZ xyz2 = new XYZ(newParallelPipeXYZ2.X, newParallelPipeXYZ2.Y, levelOffset / 304.8);
			double num = xyz.DistanceTo(xyz2) * slope / 100.0;
			XYZ start2 = new XYZ(newParallelPipeXYZ.X, newParallelPipeXYZ.Y, levelOffset / 304.8);
			XYZ end2 = new XYZ(newParallelPipeXYZ2.X, newParallelPipeXYZ2.Y, levelOffset / 304.8 + num);
			Pipe result = document.CreatHYPipe(pipingSystemType, pipeType, genLevel, start2, end2, paraDiameter);
			document.Regenerate();
			return result;
		}

		public XYZ getNewParallelPipeXYZ(XYZ oldXYZ, Line pipeline, double offset, XYZ point)
		{
			XYZ result = null;
			XYZ hyendPoint = pipeline.GetEndPoint(0);
			XYZ hyendPoint2 = pipeline.GetEndPoint(1);
			Line line = YJKLineEx.YJKGetBound(hyendPoint, hyendPoint2);
			if (Math.Abs(hyendPoint.Y - hyendPoint2.Y) < 1E-09)
			{
				if (point.Y > hyendPoint.Y)
				{
					result = new XYZ(oldXYZ.X, oldXYZ.Y + offset / 304.8, oldXYZ.Z);
				}
				else if (point.Y < hyendPoint.Y)
				{
					result = new XYZ(oldXYZ.X, oldXYZ.Y - offset / 304.8, oldXYZ.Z);
				}
			}
			else if (Math.Abs(hyendPoint.X - hyendPoint2.X) < 1E-10)
			{
				if (hyendPoint.X > point.X)
				{
					result = new XYZ(oldXYZ.X - offset / 304.8, oldXYZ.Y, oldXYZ.Z);
				}
				else if (hyendPoint.X < point.X)
				{
					result = new XYZ(oldXYZ.X + offset / 304.8, oldXYZ.Y, oldXYZ.Z);
				}
			}
			else if (hyendPoint.Y != hyendPoint2.Y && hyendPoint.X != hyendPoint2.X)
			{
				double num = Math.Abs((hyendPoint2.X - hyendPoint.X) / line.Length) * (offset / 304.8);
				double num2 = Math.Abs((hyendPoint2.Y - hyendPoint.Y) / line.Length) * (offset / 304.8);
				if (this.lookForK(hyendPoint, hyendPoint2) < 1E-06)
				{
					if (this.isAnotherSite(hyendPoint, hyendPoint2, point))
					{
						result = new XYZ(oldXYZ.X + num2, oldXYZ.Y + num, oldXYZ.Z);
					}
					else
					{
						result = new XYZ(oldXYZ.X - num2, oldXYZ.Y - num, oldXYZ.Z);
					}
				}
				else if (this.lookForK(hyendPoint, hyendPoint2) > 1E-06)
				{
					if (this.isAnotherSite(hyendPoint, hyendPoint2, point))
					{
						result = new XYZ(oldXYZ.X - num2, oldXYZ.Y + num, oldXYZ.Z);
					}
					else
					{
						result = new XYZ(oldXYZ.X + num2, oldXYZ.Y - num, oldXYZ.Z);
					}
				}
			}
			return result;
		}

		public bool judgePointIsAnotherLine(Line pipeline, XYZ point)
		{
			bool result = false;
			XYZ hyendPoint = pipeline.GetEndPoint(0);
			XYZ hyendPoint2 = pipeline.GetEndPoint(1);
			YJKLineEx.YJKGetBound(hyendPoint, hyendPoint2);
			if (Math.Abs(hyendPoint.Y - hyendPoint2.Y) < 1E-06)
			{
				if (point.Y > hyendPoint.Y)
				{
					result = true;
				}
				else if (point.Y < hyendPoint.Y)
				{
					result = false;
				}
			}
			else if (Math.Abs(hyendPoint.X - hyendPoint2.X) < 1E-07)
			{
				if (hyendPoint.X > point.X)
				{
					result = false;
				}
				else if (hyendPoint.X < point.X)
				{
					result = true;
				}
			}
			else if (hyendPoint.Y != hyendPoint2.Y && hyendPoint.X != hyendPoint2.X)
			{
				if (this.lookForK(hyendPoint, hyendPoint2) < 1E-06)
				{
					result = this.isAnotherSite(hyendPoint, hyendPoint2, point);
				}
				else if (this.lookForK(hyendPoint, hyendPoint2) > 1E-06)
				{
					result = this.isAnotherSite(hyendPoint, hyendPoint2, point);
				}
			}
			return result;
		}

		public bool isAnotherSite(XYZ p1, XYZ p2, XYZ point)
		{
			bool result = false;
			double num = this.lookForK(p1, p2);
			if (point.Y - p1.Y - num * (point.X - p1.X) > 0.0)
			{
				result = true;
			}
			return result;
		}

		public double lookForK(XYZ start, XYZ end)
		{
			double x = start.X;
			double x2 = end.X;
			double y = start.Y;
			return (end.Y - y) / (x2 - x);
		}

		private Pipe CopyPipe(Autodesk.Revit.DB.Document document)
		{
			IEnumerable<Element> elementByClass = YJKElementFilter.GetElementByClass(typeof(Pipe), document);
			Pipe result = null;
			foreach (Element element in elementByClass)
			{
				if (element != null && element is Pipe && ((Pipe)element).get_Parameter(BuiltInParameter.RBS_PIPE_SLOPE).AsDouble().ToString() == "0" && ((Pipe)element).get_Parameter(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM).AsValueString() != "未定义")
				{
					result = (Pipe)element;
					break;
				}
			}
			return result;
		}
	}
}
